/**
 *  WiiEventHandler
 *  Functions to process the different wiimote events
 */

#include "WiiEventHandler.h"
#include "wiiuse.h"
#include "WiimoteManager.h"


/**
 *	@brief Callback that handles an event.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *
 *	This function is called automatically by the wiiuse library when an
 *	event occurs on the specified wiimote.
 */
//void handle_event(struct wiimote_t* wm, int wmID, int (*retroLlamada)(int wmButton, int wmID) ) {
void handle_event(struct wiimote_t* wm, int wmID, wmCallbacks *functions) {
    	printf("\n\n--- EVENT OCURRED [id %i] ---\n", wm->unid);

        // Do action just if the function is defined
        if(functions->wmButtonPressedAction != NULL){
            /* if a button is pressed, report it */
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_A))       functions->wmButtonPressedAction(WIIMOTE_BUTTON_A, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_B))       functions->wmButtonPressedAction(WIIMOTE_BUTTON_B, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP))      functions->wmButtonPressedAction(WIIMOTE_BUTTON_UP, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN))    functions->wmButtonPressedAction(WIIMOTE_BUTTON_DOWN, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT))    functions->wmButtonPressedAction(WIIMOTE_BUTTON_LEFT, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT))   functions->wmButtonPressedAction(WIIMOTE_BUTTON_RIGHT, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS))    functions->wmButtonPressedAction(WIIMOTE_BUTTON_MINUS, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS))     functions->wmButtonPressedAction(WIIMOTE_BUTTON_PLUS, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE))     functions->wmButtonPressedAction(WIIMOTE_BUTTON_ONE, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_TWO))     functions->wmButtonPressedAction(WIIMOTE_BUTTON_TWO, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_HOME))    functions->wmButtonPressedAction(WIIMOTE_BUTTON_HOME, wmID);
        }

         // Do action just if the function is defined
        if(functions->wmButtonReleasedAction != NULL){
            /* I f a button is released, report it */
            if (IS_RELEASED(wm, WIIMOTE_BUTTON_A))       functions->wmButtonReleasedAction(WIIMOTE_BUTTON_A, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_B))       functions->wmButtonReleasedAction(WIIMOTE_BUTTON_B, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP))      functions->wmButtonReleasedAction(WIIMOTE_BUTTON_UP, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN))    functions->wmButtonReleasedAction(WIIMOTE_BUTTON_DOWN, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT))    functions->wmButtonReleasedAction(WIIMOTE_BUTTON_LEFT, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT))   functions->wmButtonReleasedAction(WIIMOTE_BUTTON_RIGHT, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS))    functions->wmButtonReleasedAction(WIIMOTE_BUTTON_MINUS, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS))     functions->wmButtonReleasedAction(WIIMOTE_BUTTON_PLUS, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE))     functions->wmButtonReleasedAction(WIIMOTE_BUTTON_ONE, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_TWO))     functions->wmButtonReleasedAction(WIIMOTE_BUTTON_TWO, wmID);
            if (IS_PRESSED(wm, WIIMOTE_BUTTON_HOME))    functions->wmButtonReleasedAction(WIIMOTE_BUTTON_HOME, wmID);
        }

        // Do action just if the function is defined
        if(functions->wmAccelerometerAction != NULL){
            /* if the accelerometer is turned on then update angles */
            if (WIIUSE_USING_ACC(wm)) {
                functions->wmAccelerometerAction(   wm->orient.roll,
                                                    wm->orient.pitch,
                                                    wm->orient.yaw,
                                                    wmID);
            }
        }

        if(functions->wmIRAction != NULL){
            /*
             *	If IR tracking is enabled then send the information to the wmIRAction function
             *      Also make sure that we see at least 1 dot.
             *      The wiimote knows exactly where every point is, and its id.
             */
            if (WIIUSE_USING_IR(wm)) {
                    int i = 0;

                    /* go through each of the 4 possible IR */
                    for (; i < 4; ++i) {
                            /* check if the source is visible */
                            if (wm->ir.dot[i].visible){
                                    //printf("IR source %i: (%u, %u)\n", i, wm->ir.dot[i].x, wm->ir.dot[i].y);
                                    functions->wmIRAction(wm->ir.dot[i].x, wm->ir.dot[i].y, i, wmID);
                            }
                    }

                    printf("IR cursor: (%u, %u)\n", wm->ir.x, wm->ir.y);
                    printf("Point Number: %u\n", wm->ir.num_dots);
                    printf("IR z distance: %f\n", wm->ir.z);
            }
        }

        //TODO modify code to able wiimote support for expansions

	/* show events specific to supported expansions */
	if (wm->exp.type == EXP_NUNCHUK) {
		/* nunchuk */
		struct nunchuk_t* nc = (nunchuk_t*)&wm->exp.nunchuk;

		if (IS_PRESSED(nc, NUNCHUK_BUTTON_C))		printf("Nunchuk: C pressed\n");
		if (IS_PRESSED(nc, NUNCHUK_BUTTON_Z))		printf("Nunchuk: Z pressed\n");

		printf("nunchuk roll  = %f\n", nc->orient.roll);
		printf("nunchuk pitch = %f\n", nc->orient.pitch);
		printf("nunchuk yaw   = %f\n", nc->orient.yaw);

		printf("nunchuk joystick angle:     %f\n", nc->js.ang);
		printf("nunchuk joystick magnitude: %f\n", nc->js.mag);
	} else if (wm->exp.type == EXP_CLASSIC) {
		/* classic controller */
		struct classic_ctrl_t* cc = (classic_ctrl_t*)&wm->exp.classic;

		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZL))			printf("Classic: ZL pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_B))			printf("Classic: B pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_Y))			printf("Classic: Y pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_A))			printf("Classic: A pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_X))			printf("Classic: X pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZR))			printf("Classic: ZR pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_LEFT))		printf("Classic: LEFT pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_UP))			printf("Classic: UP pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_RIGHT))		printf("Classic: RIGHT pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_DOWN))		printf("Classic: DOWN pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_L))		printf("Classic: FULL L pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_MINUS))		printf("Classic: MINUS pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_HOME))		printf("Classic: HOME pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_PLUS))		printf("Classic: PLUS pressed\n");
		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_R))		printf("Classic: FULL R pressed\n");

		printf("classic L button pressed:         %f\n", cc->l_shoulder);
		printf("classic R button pressed:         %f\n", cc->r_shoulder);
		printf("classic left joystick angle:      %f\n", cc->ljs.ang);
		printf("classic left joystick magnitude:  %f\n", cc->ljs.mag);
		printf("classic right joystick angle:     %f\n", cc->rjs.ang);
		printf("classic right joystick magnitude: %f\n", cc->rjs.mag);
	} else if (wm->exp.type == EXP_GUITAR_HERO_3) {
		/* guitar hero 3 guitar */
		struct guitar_hero_3_t* gh3 = (guitar_hero_3_t*)&wm->exp.gh3;

		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_UP))		printf("Guitar: Strum Up pressed\n");
		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_DOWN))	printf("Guitar: Strum Down pressed\n");
		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_YELLOW))		printf("Guitar: Yellow pressed\n");
		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_GREEN))		printf("Guitar: Green pressed\n");
		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_BLUE))			printf("Guitar: Blue pressed\n");
		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_RED))			printf("Guitar: Red pressed\n");
		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_ORANGE))		printf("Guitar: Orange pressed\n");
		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_PLUS))			printf("Guitar: Plus pressed\n");
		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_MINUS))		printf("Guitar: Minus pressed\n");

		printf("Guitar whammy bar:          %f\n", gh3->whammy_bar);
		printf("Guitar joystick angle:      %f\n", gh3->js.ang);
		printf("Guitar joystick magnitude:  %f\n", gh3->js.mag);
	}
}


/**
 *	@brief Callback that handles a read event.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *	@param data		Pointer to the filled data block.
 *	@param len		Length in bytes of the data block.
 *
 *	This function is called automatically by the wiiuse library when
 *	the wiimote has returned the full data requested by a previous
 *	call to wiiuse_read_data().
 *
 *	You can read data on the wiimote, such as Mii data, if
 *	you know the offset address and the length.
 *
 *	The \a data pointer was specified on the call to wiiuse_read_data().
 *	At the time of this function being called, it is not safe to deallocate
 *	this buffer.
 */
void handle_read(struct wiimote_t* wm, byte* data, unsigned short len) {
	int i = 0;

	printf("\n\n--- DATA READ [wiimote id %i] ---\n", wm->unid);
	printf("finished read of size %i\n", len);
	for (; i < len; ++i) {
		if (!(i%16))
			printf("\n");
		printf("%x ", data[i]);
	}
	printf("\n\n");
}


/**
 *	@brief Callback that handles a controller status event.
 *
 *	@param wm				Pointer to a wiimote_t structure.
 *	@param attachment		Is there an attachment? (1 for yes, 0 for no)
 *	@param speaker			Is the speaker enabled? (1 for yes, 0 for no)
 *	@param ir				Is the IR support enabled? (1 for yes, 0 for no)
 *	@param led				What LEDs are lit.
 *	@param battery_level	Battery level, between 0.0 (0%) and 1.0 (100%).
 *
 *	This occurs when either the controller status changed
 *	or the controller status was requested explicitly by
 *	wiiuse_status().
 *
 *	One reason the status can change is if the nunchuk was
 *	inserted or removed from the expansion port.
 */
void handle_ctrl_status(struct wiimote_t* wm) {
	printf("\n\n--- CONTROLLER STATUS [wiimote id %i] ---\n", wm->unid);

	printf("attachment:      %i\n", wm->exp.type);
	printf("speaker:         %i\n", WIIUSE_USING_SPEAKER(wm));
	printf("ir:              %i\n", WIIUSE_USING_IR(wm));
	printf("leds:            %i %i %i %i\n", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4));
	printf("battery:         %f %%\n", wm->battery_level);
}


/**
 *	@brief Callback that handles a disconnection event.
 *
 *	@param wm				Pointer to a wiimote_t structure.
 *
 *	This can happen if the POWER button is pressed, or
 *	if the connection is interrupted.
 */
void handle_disconnect(wiimote* wm) {
	printf("\n\n--- DISCONNECTED [wiimote id %i] ---\n", wm->unid);
}


void test(struct wiimote_t* wm, byte* data, unsigned short len) {
	printf("test: %i [%x %x %x %x]\n", len, data[0], data[1], data[2], data[3]);
}
